/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.testis.utils;

import java.io.IOException;
import java.io.InputStream;


/**
 * A class to execute terminal applications
 * @author nurhat
 */
public class TerminalApplicationExecutor extends Thread
{

    /**
     * To read error output stream of terminal app
     */
    AtofStreamReader m_errorStream = null;
    /**
     * To read input stream of terminal app
     */
    AtofStreamReader m_inputStream = null;
    /**
     * path of application
     */
    String m_appPath;
    /**
     * paremeters to be used
     */
    String m_appPathArray[];
    /**
     * paremeters to be used
     */
    String m_parameters;
    /**
     * exit value
     */
    private int m_exitValue;


    public TerminalApplicationExecutor(String appPath)
    {
        m_appPath = appPath;
        m_parameters = "";

    }


    public TerminalApplicationExecutor(String appPath[])
    {
        m_appPathArray = appPath;
    }


    public TerminalApplicationExecutor(String appPath,
                                       String parameters)
    {
        m_appPath = appPath;
        m_parameters = parameters;

    }


    /**
     * End execution of terminall application
     */
    public void endExec()
    {
        if (m_errorStream != null) {
            if (m_errorStream.isAlive()) {
                try {
                    m_errorStream.interrupt();
                    m_errorStream.join(2000);
                } catch (InterruptedException ex) {
                }
            }
        }
        if (m_inputStream != null) {
            if (m_inputStream.isAlive()) {
                try {
                    m_inputStream.join(1000);
                } catch (InterruptedException ex) {
                }
            }
        }
    }


    @Override
    public void run()
    {
        int exitValue = 4;
        try {
            Thread.sleep(2000);
            exitValue = runExec();
            setExitValue(exitValue);
        } catch (IOException ex) {
        } catch (InterruptedException ex) {
        }
    }


    /**
     * Execute terminal application
     * @return exit code of terminal application
     * @throws java.io.IOException
     * @throws java.lang.InterruptedException
     */
    public int runExec() throws IOException, InterruptedException
    {
        Runtime rt = Runtime.getRuntime();
        Process pr = null;
        if (m_appPathArray != null) {
            pr = rt.exec(m_appPathArray);
        }
        else {
            pr = rt.exec(m_appPath + " " + m_parameters);
        }
        m_errorStream = new AtofStreamReader(pr.getErrorStream());
        m_inputStream = new AtofStreamReader(pr.getInputStream());

        pr.getOutputStream().close();
        m_errorStream.start();
        m_inputStream.start();
        int exitVal = pr.waitFor();
        endExec();
        return exitVal;
    }


    /**
     * Get output of terminall application
     * @return
     */
    public String getOutputString()
    {
        if (m_inputStream != null) {
            return m_inputStream.m_outputStringBuilder.toString();
        }
        return null;
    }


    /**
     * Get error output of terminall application
     * @return
     */
    public String getErrorString()
    {
        if (m_errorStream != null) {
            return m_errorStream.m_outputStringBuilder.toString();
        }
        return null;
    }


    public int getExitValue()
    {
        return m_exitValue;
    }


    public void setExitValue(int m_exitValue)
    {
        this.m_exitValue = m_exitValue;
    }
}


class AtofStreamReader extends Thread
{

    InputStream m_inputStream;
    StringBuilder m_outputStringBuilder;


    AtofStreamReader(InputStream is)
    {
        this.m_inputStream = is;
        m_outputStringBuilder = new StringBuilder();
    }


    @Override
    public void run()
    {
        try {
            int c;

            while ((c = m_inputStream.read()) != -1) {
                m_outputStringBuilder.append((char) c);
            }
        } catch (IOException e) {
        } catch (Exception e) {
        } finally {
            if (m_inputStream != null) {
                try {
                    m_inputStream.close();
                } catch (IOException ex) {
                }
            }
        }
    }
}
